/**
 * 
 */
package network.communication;

import java.io.IOException;
import java.nio.ByteBuffer;

import commons.exception.ClosedConnectionException;

/**
 * A Connection is an abstraction to a network connection between two processes.
 * It protects the client code to depend on low-level network libraries, such as
 * Sockets and Streams. This interface provides methods for both nodes of the
 * connection (the sender node and the destination node) to send and access
 * data, so it can (and should) be used in both sides.
 * 
 * @author Armstrong Mardilson da Silva Goes
 * 
 */
public interface Connection {

	/**
	 * Closes this Connection to operations. After close, all the attempts to
	 * use this Connection will cause a ClosedConnectionException to be thrown.
	 * This method may need to close some streams used to write and read data.
	 * 
	 * @throws IOException
	 *             If there's an error in the underlying streams closure.
	 * @throws ClosedConnectionException
	 *             If the Connection is already closed.
	 */
	void close() throws IOException, ClosedConnectionException;

	/**
	 * Signals if this Connection is closed or not.
	 * 
	 * @return The Connection state.
	 */
	boolean isClosed();

	/**
	 * This method reads a Byte from the network. It hangs until the Byte is
	 * read or there's a failure in the reading.
	 * 
	 * @return The read Byte
	 * @throws IOException
	 *             If there's an error in the reading, such as exceptions thrown
	 *             by the underlying streams.
	 * @throws ClosedConnectionException
	 *             If the Connection is closed.
	 */
	Byte readByte() throws IOException, ClosedConnectionException;

	/**
	 * This method reads a ByteBuffer from the network. It hangs until the data
	 * is fully read or there's a failure in the reading. Note there is no
	 * guarantee that one call to this method will read all the data written by
	 * one call to {@link Connection.writeByteBuffer}.
	 * 
	 * @return The read ByteBuffer
	 * @throws IOException
	 *             If there's an error in the reading, such as exceptions thrown
	 *             by the underlying streams.
	 * @throws ClosedConnectionException
	 *             If the Connection is closed.
	 */
	ByteBuffer readByteBuffer() throws IOException, ClosedConnectionException;

	/**
	 * This method reads a String from the network. It hangs until the String is
	 * fully read or there's a failure in the reading.
	 * 
	 * @return The read String
	 * @throws IOException
	 *             If there's an error in the reading, such as exceptions thrown
	 *             by the underlying streams.
	 * @throws ClosedConnectionException
	 *             If the Connection is closed.
	 */
	String readString() throws IOException, ClosedConnectionException;

	/**
	 * This method writes a Byte on the network. It hangs until the Byte is
	 * written or there's a failure in the writing.
	 * 
	 * @param toWrite
	 *            The Byte to write
	 * @throws IOException
	 *             If there's an error in the writing, such as exceptions thrown
	 *             by the underlying streams.
	 * @throws ClosedConnectionException
	 *             If the Connection is closed.
	 * @throws IllegalArgumentException
	 *             If toWrite is null.
	 */
	void writeByte(Byte toWrite) throws IOException, ClosedConnectionException;

	/**
	 * This method writes a ByteBuffer on the network. It hangs until the data
	 * is fully written or there's a failure in the writing. There's no
	 * guarantee on the method used to write the data. The Connection may split
	 * the data into small slices and write them separately or use other method.
	 * 
	 * @param buffer
	 *            The ByteBuffer to write
	 * @throws IOException
	 *             If there's an error in the writing, such as exceptions thrown
	 *             by the underlying streams.
	 * @throws ClosedConnectionException
	 *             If the Connection is closed.
	 * @throws IllegalArgumentException
	 *             If buffer is null.
	 */
	void writeByteBuffer(ByteBuffer buffer) throws IOException,
			ClosedConnectionException;

	/**
	 * This method writes a String on the network. It hangs until the String is
	 * fully written or there's a failure in the writing.
	 * 
	 * @param toWrite
	 *            The String to write
	 * @throws IOException
	 *             If there's an error in the writing, such as exceptions thrown
	 *             by the underlying streams.
	 * @throws ClosedConnectionException
	 *             If the Connection is closed.
	 * @throws IllegalArgumentException
	 *             If toWrite is null.
	 */
	void writeString(String toWrite) throws IOException,
			ClosedConnectionException;
}
